# -*- coding: utf-8 -*-

import csv
import json
import time

import requests
from django.conf import settings
from django.views.decorators.http import require_GET, require_POST

from common.bankcard import db as bankcard_db
from common.bankcard.db import get_chargeable_bankcards_by_mch
from common.bankcard.model import BANK_CARD_STATUS, BANK_CARD_TYPE, BANK_DCT
from common.console import db as user_db
from common.mch import db as mch_db
from common.utils import track_logging
from common.utils import tz
from common.utils.api import check_params
from common.utils.api import token_required
from common.utils.decorator import response_wrapper, safe_wrapper
from common.utils.exceptions import ParamError
from common.utils.tz import (
    utc_to_local_str
)

_LOGGER = track_logging.getLogger(__name__)


@require_POST
@token_required
@response_wrapper
def create_bankcard(req):
    param_dct = json.loads(req.body)
    check_params(param_dct, ['name', 'account_holder',
                             'account_number', 'bank', 'region', 'phone', 'subbranch', 'calculate_balance']
                 )
    bankcard = bankcard_db.check_bankcard_exists(param_dct['name'], param_dct['account_number'])
    if bankcard:
        raise ParamError('bankcard exists')
    bankcard = bankcard_db.create_bankcard(param_dct)
    return bankcard.as_dict()


@require_POST
@token_required
@response_wrapper
def batch_create_bankcard(req):
    upload_file = req.FILES
    data = csv.DictReader(req.FILES['file'])
    bankcards = bankcard_db.batch_create_bankcard(data)
    return {}


@require_POST
@token_required
@response_wrapper
@safe_wrapper
def create_peroid(req):
    param_dct = json.loads(req.body)
    check_params(param_dct, ['bank', 'card_type', 'daily_max_recharge',
                             'daily_max_recharge_count', 'daily_max_withdraw', 'daily_max_withdraw_count',
                             'max_recharge', 'max_withdraw', 'max_day']
                 )
    if bankcard_db.check_peroid_exists(param_dct['card_type'], param_dct['bank']):
        raise ParamError('period already exists')
    bankcard_peroid = bankcard_db.create_peroid(param_dct)
    return bankcard_peroid.as_dict()


@require_GET
@token_required
@response_wrapper
def list_bankcard(req):
    query_dct = req.GET.dict()
    cond = user_db.get_mchids_filter_by_user(req.user_id)
    if cond and query_dct.get('mch_id') is None:
        query_dct['mch_id'] = cond
    items, total_count = bankcard_db.list_bankcard(query_dct)
    star_dct = bankcard_db.get_all_bankcard_stars()
    bankdata_dct = bankcard_db.get_all_bankcard_data()
    mch_dct = mch_db.get_mch_dct()
    resp_items = []
    for item in items:
        data = item.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['bank_en'] = BANK_DCT.get(data['bank'], '')
        data['mch_id'] = mch_dct.get(data['mch_id'], '')
        data['stars'] = star_dct.get(data['id'], [])
        data['daily_recharge'] = bankdata_dct.get(data['id'], {}).get('daily_recharge_total', 0)
        data['daily_withdraw'] = bankdata_dct.get(data['id'], {}).get('daily_withdraw_total', 0)
        data['daily_recharge_count'] = bankdata_dct.get(data['id'], {}).get('daily_recharge_count', 0)
        data['daily_withdraw_count'] = bankdata_dct.get(data['id'], {}).get('daily_withdraw_count', 0)
        resp_items.append(data)

    return {'list': resp_items, 'page': query_dct.get('$page', 1),
            'size': len(resp_items), 'total_count': total_count}


@require_GET
@token_required
@response_wrapper
def list_chargeable_bankcard(req, mch_id):
    mch_id = int(mch_id)
    bankcards = get_chargeable_bankcards_by_mch(mch_id)
    return {
        'bankcards': [
            dict(id=e.id, name=e.name, bank=e.bank, account_holder=e.account_holder, account_number=e.account_number)
            for e in
            bankcards
        ]
    }


@require_GET
@response_wrapper
def list_our_bankcard(req):
    client_ip = req.META['REMOTE_ADDR']
    _LOGGER.info('list_our_bankcard client_ip : %s', client_ip)
    # if client_ip not in ['103.230.240.107', '58.64.207.180']:
    #     raise ParamError('ip %s not in white list!' % client_ip)
    query_dct = req.GET.dict()
    query_dct['card_type'] = str(BANK_CARD_TYPE.ORECHARGE)
    query_dct['status'] = str(BANK_CARD_STATUS.AVAILABLE)
    items, total_count = bankcard_db.list_bankcard(query_dct)
    resp_items = []
    for item in items:
        data = {}
        data['account_number'] = item.account_number
        data['account_holder'] = item.account_holder
        data['bank'] = item.bank
        data['region'] = item.region
        data['phone'] = item.phone
        data['email'] = item.email
        data['subbranch'] = item.subbranch
        data['account'] = item.account
        data['password'] = item.password
        data['bank_en'] = BANK_DCT.get(data['bank'], '')
        resp_items.append(data)
    return {'list': resp_items}


@require_GET
@token_required
@response_wrapper
def list_bankcard_peroid(req):
    query_dct = req.GET.dict()
    items, total_count = bankcard_db.list_bankcard_peroid(query_dct)
    resp_items = []
    for item in items:
        data = item.as_dict()
        data['bank_en'] = BANK_DCT.get(data['bank'], '')
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        resp_items.append(data)

    return {'list': resp_items, 'page': query_dct.get('$page', 1),
            'size': len(resp_items), 'total_count': total_count}


@require_GET
@token_required
@response_wrapper
def get_bankcard_info(req, card_id):
    bankcard = bankcard_db.get_bankcard(card_id)
    if not bankcard:
        raise ParamError('bankcard %s not exist' % card_id)
    data = bankcard.as_dict()
    data['created_at'] = utc_to_local_str(data['created_at'])
    data['updated_at'] = utc_to_local_str(data['updated_at'])
    data.pop('account', None)
    data.pop('password', None)
    return data


@require_GET
@token_required
@response_wrapper
def get_bankcard_report(req, card_id):
    bankcard = bankcard_db.get_bankcard(card_id)
    if not bankcard:
        raise ParamError('bankcard %s not exist' % card_id)
    bankcard_data = bankcard_db.get_bankcard_data(card_id)
    resp = bankcard_data.as_dict()
    resp['calculate_balance'] = bankcard.calculate_balance
    resp['real_balance'] = bankcard.real_balance
    resp['hour'] = (int(time.time()) - tz.to_ts(bankcard.created_at)) / 3600
    return resp


@require_GET
@token_required
@response_wrapper
def get_bankcard_peroid(req, peroid_id):
    bankcard_peroid = bankcard_db.get_bankcard_peroid(peroid_id)
    if not bankcard_peroid:
        raise ParamError('bankcard peroid %s not exist' % peroid_id)
    data = bankcard_peroid.as_dict()
    data['created_at'] = utc_to_local_str(data['created_at'])
    data['updated_at'] = utc_to_local_str(data['updated_at'])
    return data


@require_POST
@token_required
@response_wrapper
@safe_wrapper
def update_bankcard_peroid(req, peroid_id):
    param_dct = json.loads(req.body)
    valid_params = ['daily_max_recharge', 'daily_max_recharge_count',
                    'daily_max_withdraw', 'daily_max_withdraw_count', 'max_recharge',
                    'max_withdraw', 'max_day'
                    ]
    # for k in param_dct:
    #    if k not in valid_params:
    #        raise ParamError('param %s not allowed' % k)

    # if bankcard_db.check_peroid_exists(param_dct['card_type'], param_dct['bank']):
    #    raise ParamError('period already exists')
    bankcard_period = bankcard_db.update_bankcard_peroid(peroid_id, param_dct)
    return bankcard_period.as_dict()


@require_POST
@token_required
@response_wrapper
def delete_bankcard_peroid(req, peroid_id):
    bankcard_db.delete_bankcard_peroid(peroid_id)
    return {}


@require_POST
@token_required
@response_wrapper
def delete_bankcard(req, card_id):
    bankcard = bankcard_db.get_bankcard(card_id)
    if not bankcard or bankcard.status == BANK_CARD_STATUS.AVAILABLE:
        raise ParamError('Active card could not be deleted')
    bankcard_db.delete_bankcard(card_id)
    return {}


@require_POST
@token_required
@response_wrapper
@safe_wrapper
def update_bankcard_info(req, card_id):
    param_dct = json.loads(req.body)
    param_dct.pop('g_code')
    valid_params = ['mch_id', 'card_type', 'email', 'phone', 'usheild_date', 'desc', 'real_balance', 'bank']

    for k in param_dct:
        if k not in valid_params:
            raise ParamError('param %s not allowed' % k)
        # if k == 'card_type':
        #     bankcard = bankcard_db.get_bankcard(card_id)
        #     if bankcard.card_type != BANK_CARD_TYPE.TEST:
        #         raise ParamError('card_type %s not editable' % bankcard.status)

    bank_card = bankcard_db.update_bankcard_info(card_id, param_dct)
    return bank_card.as_dict()


@require_POST
@token_required
@response_wrapper
def update_bankcard_status(req, card_id):
    param_dct = json.loads(req.body)
    check_params(param_dct, ['status'])
    bankcard_db.update_bankcard_info(card_id, {'status': param_dct['status']})
    bankcard = bankcard_db.get_bankcard(card_id)
    if bankcard and bankcard.card_type == BANK_CARD_TYPE.ORECHARGE:
        query_dct = {}
        query_dct['card_type'] = str(BANK_CARD_TYPE.ORECHARGE)
        query_dct['status'] = str(BANK_CARD_STATUS.AVAILABLE)
        items, total_count = bankcard_db.list_bankcard(query_dct)
        resp_items = []
        for item in items:
            data = {}
            data['account_number'] = item.account_number
            data['account_holder'] = item.account_holder
            data['bank'] = item.bank
            data['region'] = item.region
            data['phone'] = item.phone
            data['email'] = item.email
            data['subbranch'] = item.subbranch
            data['account'] = item.account
            data['password'] = item.password
            data['bank_en'] = BANK_DCT.get(data['bank'], '')
            resp_items.append(data)
        rsp = {
            "msg": "",
            "status": 0,
            "data": {
            }
        }
        rsp['data']['list'] = resp_items
        j = json.dumps(rsp)
        _LOGGER.info('NOTIFY_HYDRA_BANKCARDS data: %s', j)
        headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
        res = requests.post(settings.NOTIFY_HYDRA_BANKCARDS, data=j, headers=headers, timeout=5).text
        _LOGGER.info('NOTIFY_HYDRA_BANKCARDS rsp: %s', res)
    return {}


@require_GET
@token_required
@response_wrapper
def get_bankcard_password(req, card_id):
    bankcard = bankcard_db.get_bankcard(card_id)
    if not bankcard:
        raise ParamError('bankcard %s not exist' % card_id)
    return {
        "account": bankcard.account,
        "password": bankcard.password
    }


@require_POST
@token_required
@response_wrapper
def update_bankcard_password(req, card_id):
    param_dct = json.loads(req.body)
    valid_params = ['account', 'password']
    for k in param_dct:
        if k not in valid_params:
            raise ParamError('param %s not allowed' % k)
    bankcard_db.update_bankcard_info(card_id, param_dct)
    return {}


@require_GET
@token_required
@response_wrapper
def get_bankcard_stars(req, card_id):
    stars = bankcard_db.get_bankcard_stars(card_id)
    return {
        "stars": stars
    }


@require_POST
@token_required
@response_wrapper
def update_bankcard_stars(req, card_id):
    param_dct = json.loads(req.body)
    check_params(param_dct, ['stars'])
    stars = bankcard_db.update_bankcard_stars(card_id, param_dct['stars'])
    return {}
